home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / lib / fglut / glut_cindex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  9.8 KB  |  321 lines

  1. /* Copyright (c) Mark J. Kilgard, 1994, 1996. */
  2.  
  3. /* This program is freely distributable without licensing fees 
  4.    and is provided without guarantee or warrantee expressed or 
  5.    implied. This program is -not- in the public domain. */
  6.  
  7. #include <stdlib.h>
  8. #include <GL/glut.h>
  9. #include "glutint.h"
  10. #include "layerutil.h"
  11.  
  12. GLUTcolormap *__glutColormapList = NULL;
  13.  
  14. static GLUTcolormap *
  15. associateNewColormap(XVisualInfo * vis)
  16. {
  17.   GLUTcolormap *cmap;
  18.   int transparentPixel, i;
  19.   unsigned long pixels[255];
  20.  
  21.   cmap = (GLUTcolormap *) malloc(sizeof(GLUTcolormap));
  22.   if (!cmap)
  23.     __glutFatalError("out of memory.");
  24.   cmap->visual = vis->visual;
  25.   cmap->refcnt = 1;
  26.   cmap->size = vis->visual->map_entries;
  27.   cmap->cells = (GLUTcolorcell *)
  28.     malloc(sizeof(GLUTcolorcell) * cmap->size);
  29.   /* make all color cell entries be invalid */
  30.   for (i = cmap->size - 1; i >= 0; i--) {
  31.     cmap->cells[i].component[GLUT_RED] = -1.0;
  32.     cmap->cells[i].component[GLUT_GREEN] = -1.0;
  33.     cmap->cells[i].component[GLUT_BLUE] = -1.0;
  34.   }
  35.   if (!cmap->cells)
  36.     __glutFatalError("out of memory.");
  37.   transparentPixel = __glutGetTransparentPixel(__glutDisplay, vis);
  38.   if (transparentPixel == -1 || transparentPixel >= vis->visual->map_entries) {
  39.  
  40.     /* If there is no transparent pixel or if the transparent
  41.        pixel is outside the range of valid colormap cells (HP
  42.        can implement their overlays this smart way since their
  43.        transparent pixel is 255), we can AllocAll the colormap.
  44.        See note below.  */
  45.  
  46.     cmap->cmap = XCreateColormap(__glutDisplay,
  47.       __glutRoot, vis->visual, AllocAll);
  48.   } else {
  49.  
  50.     /* On machines where zero (or some other value in the range
  51.        of 0 through map_entries-1), BadAlloc may be generated
  52.        when an AllocAll overlay colormap is allocated since the
  53.        transparent pixel precludes all the cells in the colormap
  54.        being allocated (the transparent pixel is pre-allocated).
  55.        So in this case, use XAllocColorCells to allocate
  56.        map_entries-1 pixels (that is, all but the transparent
  57.        pixel.  */
  58.  
  59.     cmap->cmap = XCreateColormap(__glutDisplay,
  60.       __glutRoot, vis->visual, AllocNone);
  61.     XAllocColorCells(__glutDisplay, cmap->cmap, False, 0, 0,
  62.       pixels, vis->visual->map_entries - 1);
  63.   }
  64.   cmap->next = __glutColormapList;
  65.   __glutColormapList = cmap;
  66.   return cmap;
  67. }
  68.  
  69. GLUTcolormap *
  70. __glutAssociateColormap(XVisualInfo * vis)
  71. {
  72.   GLUTcolormap *cmap = __glutColormapList;
  73.  
  74.   while (cmap != NULL) {
  75.     /* Play safe: compare visual IDs, not Visual*'s */
  76.     if (cmap->visual->visualid == vis->visual->visualid) {
  77.       /* already have created colormap for the visual */
  78.       cmap->refcnt++;
  79.       return cmap;
  80.     }
  81.     cmap = cmap->next;
  82.   }
  83.   return associateNewColormap(vis);
  84. }
  85.  
  86. #define CLAMP(i) ((i) > 1.0 ? 1.0 : ((i) < 0.0 ? 0.0 : (i)))
  87.  
  88. /* CENTRY */
  89. void
  90. glutSetColor(int ndx, GLfloat red, GLfloat green, GLfloat blue)
  91. {
  92.   GLUTcolormap *cmap, *newcmap;
  93.   XVisualInfo *vis;
  94.   XColor color;
  95.   int i;
  96.  
  97.   if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  98.     cmap = __glutCurrentWindow->colormap;
  99.     vis = __glutCurrentWindow->vis;
  100.   } else {
  101.     cmap = __glutCurrentWindow->overlay->colormap;
  102.     vis = __glutCurrentWindow->overlay->vis;
  103.     if (ndx == __glutCurrentWindow->overlay->transparentPixel) {
  104.       __glutWarning(
  105.     "glutSetColor: cannot set color of overlay transparent index %d\n",
  106.     ndx);
  107.       return;
  108.     }
  109.   }
  110.  
  111.   if (!cmap) {
  112.     __glutWarning("glutSetColor: current window is RGBA");
  113.     return;
  114.   }
  115.   if (ndx >= vis->visual->map_entries ||
  116.     ndx < 0) {
  117.     __glutWarning("glutSetColor: index %d out of range", ndx);
  118.     return;
  119.   }
  120.   if (cmap->refcnt > 1) {
  121.     GLUTwindow *toplevel;
  122.  
  123.     newcmap = associateNewColormap(vis);
  124.     cmap->refcnt--;
  125.     /* Wouldn't it be nice if XCopyColormapAndFree could be
  126.        told not to free the old colormap's entries! */
  127.     for (i = cmap->size - 1; i >= 0; i--) {
  128.       if (i == ndx) {
  129.         /* We are going to set this cell shortly! */
  130.         continue;
  131.       }
  132.       if (cmap->cells[i].component[GLUT_RED] >= 0.0) {
  133.         color.pixel = i;
  134.         newcmap->cells[i].component[GLUT_RED] =
  135.           cmap->cells[i].component[GLUT_RED];
  136.         color.red = (GLfloat) 0xffff *
  137.           cmap->cells[i].component[GLUT_RED];
  138.         newcmap->cells[i].component[GLUT_GREEN] =
  139.           cmap->cells[i].component[GLUT_GREEN];
  140.         color.green = (GLfloat) 0xffff *
  141.           cmap->cells[i].component[GLUT_GREEN];
  142.         newcmap->cells[i].component[GLUT_BLUE] =
  143.           cmap->cells[i].component[GLUT_BLUE];
  144.         color.blue = (GLfloat) 0xffff *
  145.           cmap->cells[i].component[GLUT_BLUE];
  146.         color.flags = DoRed | DoGreen | DoBlue;
  147.         XStoreColor(__glutDisplay, newcmap->cmap, &color);
  148.       } else {
  149.         /* leave unallocated entries unallocated */
  150.       }
  151.     }
  152.     cmap = newcmap;
  153.     if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  154.       __glutCurrentWindow->colormap = cmap;
  155.       __glutCurrentWindow->cmap = cmap->cmap;
  156.     } else {
  157.       __glutCurrentWindow->overlay->colormap = cmap;
  158.       __glutCurrentWindow->overlay->cmap = cmap->cmap;
  159.     }
  160.     XSetWindowColormap(__glutDisplay, __glutCurrentWindow->renderWin, cmap->cmap);
  161.  
  162.     toplevel = __glutToplevelOf(__glutCurrentWindow);
  163.     if (toplevel->cmap != cmap->cmap) {
  164.       __glutPutOnWorkList(toplevel, GLUT_COLORMAP_WORK);
  165.     }
  166.   }
  167.   color.pixel = ndx;
  168.   red = CLAMP(red);
  169.   cmap->cells[ndx].component[GLUT_RED] = red;
  170.   color.red = (GLfloat) 0xffff *red;
  171.   green = CLAMP(green);
  172.   cmap->cells[ndx].component[GLUT_GREEN] = green;
  173.   color.green = (GLfloat) 0xffff *green;
  174.   blue = CLAMP(blue);
  175.   cmap->cells[ndx].component[GLUT_BLUE] = blue;
  176.   color.blue = (GLfloat) 0xffff *blue;
  177.   color.flags = DoRed | DoGreen | DoBlue;
  178.   XStoreColor(__glutDisplay, cmap->cmap, &color);
  179. }
  180.  
  181. GLfloat
  182. glutGetColor(int ndx, int comp)
  183. {
  184.   GLUTcolormap *colormap;
  185.   XVisualInfo *vis;
  186.  
  187.   if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  188.     colormap = __glutCurrentWindow->colormap;
  189.     vis = __glutCurrentWindow->vis;
  190.   } else {
  191.     colormap = __glutCurrentWindow->overlay->colormap;
  192.     vis = __glutCurrentWindow->overlay->vis;
  193.     if (ndx == __glutCurrentWindow->overlay->transparentPixel) {
  194.       __glutWarning("glutGetColor: requesting overlay transparent index %d\n",
  195.         ndx);
  196.       return -1.0;
  197.     }
  198.   }
  199.  
  200.   if (!colormap) {
  201.     __glutWarning("glutGetColor: current window is RGBA");
  202.     return -1.0;
  203.   }
  204.   if (ndx >= vis->visual->map_entries || ndx < 0) {
  205.     __glutWarning("glutGetColor: index %d out of range", ndx);
  206.     return -1.0;
  207.   }
  208.   return colormap->cells[ndx].component[comp];
  209. }
  210. /* ENDCENTRY */
  211.  
  212. void
  213. __glutFreeColormap(GLUTcolormap * cmap)
  214. {
  215.   GLUTcolormap *cur, **prev;
  216.  
  217.   cmap->refcnt--;
  218.   if (cmap->refcnt == 0) {
  219.     /* remove from colormap list */
  220.     cur = __glutColormapList;
  221.     prev = &__glutColormapList;
  222.     while (cur) {
  223.       if (cur == cmap) {
  224.         *prev = cmap->next;
  225.         break;
  226.       }
  227.       prev = &(cur->next);
  228.       cur = cur->next;
  229.     }
  230.     /* actually free colormap */
  231.     XFreeColormap(__glutDisplay, cmap->cmap);
  232.     free(cmap->cells);
  233.     free(cmap);
  234.   }
  235. }
  236.  
  237. /* CENTRY */
  238. void
  239. glutCopyColormap(int winnum)
  240. {
  241.   GLUTwindow *window = __glutWindowList[winnum - 1];
  242.   GLUTcolormap *oldcmap, *newcmap, *copycmap;
  243.   XVisualInfo *dstvis;
  244.   XColor color;
  245.   int i, last;
  246.  
  247.   if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  248.     oldcmap = __glutCurrentWindow->colormap;
  249.     dstvis = __glutCurrentWindow->vis;
  250.     newcmap = window->colormap;
  251.   } else {
  252.     oldcmap = __glutCurrentWindow->overlay->colormap;
  253.     dstvis = __glutCurrentWindow->overlay->vis;
  254.     if (!window->overlay) {
  255.       __glutWarning("glutCopyColormap: window %d has no overlay", winnum);
  256.       return;
  257.     }
  258.     newcmap = window->overlay->colormap;
  259.   }
  260.  
  261.   if (!oldcmap) {
  262.     __glutWarning("glutCopyColormap: destination colormap must be color index");
  263.     return;
  264.   }
  265.   if (!newcmap) {
  266.     __glutWarning(
  267.       "glutCopyColormap: source colormap of window %d must be color index",
  268.       winnum);
  269.     return;
  270.   }
  271.   if (newcmap == oldcmap) {
  272.     /* Source and destination are the same; now copy needed. */
  273.     return;
  274.   }
  275.   /* Play safe: compare visual IDs, not Visual*'s */
  276.   if (newcmap->visual->visualid == oldcmap->visual->visualid) {
  277.     /* Visuals match!  "Copy" by reference...  */
  278.     __glutFreeColormap(oldcmap);
  279.     newcmap->refcnt++;
  280.     if (__glutCurrentWindow->renderWin == __glutCurrentWindow->win) {
  281.       __glutCurrentWindow->colormap = newcmap;
  282.       __glutCurrentWindow->cmap = newcmap->cmap;
  283.     } else {
  284.       __glutCurrentWindow->overlay->colormap = newcmap;
  285.       __glutCurrentWindow->overlay->cmap = newcmap->cmap;
  286.     }
  287.     XSetWindowColormap(__glutDisplay, __glutCurrentWindow->renderWin,
  288.       newcmap->cmap);
  289.     __glutPutOnWorkList(__glutToplevelOf(window), GLUT_COLORMAP_WORK);
  290.   } else {
  291.     /* Visuals different - need a distinct X colormap! */
  292.     copycmap = associateNewColormap(dstvis);
  293.     /* Wouldn't it be nice if XCopyColormapAndFree could be
  294.        told not to free the old colormap's entries! */
  295.     last = newcmap->size;
  296.     if (last > copycmap->size) {
  297.       last = copycmap->size;
  298.     }
  299.     for (i = last - 1; i >= 0; i--) {
  300.       if (newcmap->cells[i].component[GLUT_RED] >= 0.0) {
  301.         color.pixel = i;
  302.         copycmap->cells[i].component[GLUT_RED] =
  303.           newcmap->cells[i].component[GLUT_RED];
  304.         color.red = (GLfloat) 0xffff *
  305.           newcmap->cells[i].component[GLUT_RED];
  306.         copycmap->cells[i].component[GLUT_GREEN] =
  307.           newcmap->cells[i].component[GLUT_GREEN];
  308.         color.green = (GLfloat) 0xffff *
  309.           newcmap->cells[i].component[GLUT_GREEN];
  310.         copycmap->cells[i].component[GLUT_BLUE] =
  311.           newcmap->cells[i].component[GLUT_BLUE];
  312.         color.blue = (GLfloat) 0xffff *
  313.           newcmap->cells[i].component[GLUT_BLUE];
  314.         color.flags = DoRed | DoGreen | DoBlue;
  315.         XStoreColor(__glutDisplay, copycmap->cmap, &color);
  316.       }
  317.     }
  318.   }
  319. }
  320. /* ENDCENTRY */
  321.